//
// Created by thomas on 8/13/21.
//

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "proto.h"

#ifdef __cplusplus
extern "C" {
#endif

#define AKLT_XOR(raw, salt)    ((raw) ^ (salt) ^ 0x65)
#define SHIBYTE(x)             ((x) >> 8)
#define SLOBYTE(x)             ((x) & 0x00FF)
#define MKSHORT(hi, lo)        ((((hi) << 8) & 0xFF00) |  ((lo) & 0x00FF) )


int aklt_proto_encode(unsigned char *buf, unsigned short type, unsigned short cmd, unsigned short id,
                      unsigned char *data, unsigned int length, unsigned short ubflag)
{
    unsigned char salt;

    if (NULL == buf)
    {
        printf("parameters invalid\n");
        return -1;
    }

//    srand((unsigned) time(NULL));
//    salt = (unsigned char) rand();
    salt = 0x65;
    buf[0] = salt;

    buf[1] = AKLT_XOR(FIXED_TAG, salt);
    buf[2] = AKLT_XOR(SLOBYTE(ubflag), salt);
    buf[3] = AKLT_XOR(SHIBYTE(ubflag), salt);

    buf[4] = AKLT_XOR(SLOBYTE(type), salt);
    buf[5] = AKLT_XOR(SHIBYTE(type), salt);

    buf[6] = AKLT_XOR(SLOBYTE(id), salt);
    buf[7] = AKLT_XOR(SHIBYTE(id), salt);

    buf[8] = AKLT_XOR(SLOBYTE(cmd), salt);
    buf[9] = AKLT_XOR(SHIBYTE(cmd), salt);

    memcpy(&(buf[10]), data, length);

    return (int) (10 + length);
}


int aklt_proto_decode(struct akltproto *aklt, const unsigned char *data, unsigned int length)
{
    if (NULL == aklt || NULL == data)
    {
        printf("parameters invalid\n");
        return -1;
    }

    aklt->salt = data[0];
    aklt->tag = AKLT_XOR(data[1], data[0]);
    aklt->ubflag = MKSHORT(AKLT_XOR(data[3], data[0]), AKLT_XOR(data[2], data[0]));
    aklt->type = MKSHORT(AKLT_XOR(data[5], data[0]), AKLT_XOR(data[4], data[0]));
    aklt->id = MKSHORT(AKLT_XOR(data[7], data[0]), AKLT_XOR(data[6], data[0]));
    aklt->cmd = MKSHORT(AKLT_XOR(data[9], data[0]), AKLT_XOR(data[8], data[0]));

    aklt->data = (unsigned char *) malloc(length);
    if (NULL == aklt->data)
    {
        printf("malloc error\n");
        return -1;
    }

    memcpy(aklt->data, &(data[10]), length);
    aklt->size = length;

    return 0;
}

#ifdef __cplusplus
}
#endif
